package com.tianji.common.aspect;

import com.tianji.common.anno.RepeatSubmit;
import com.tianji.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import java.util.concurrent.TimeUnit;

import static com.tianji.common.constant.RepeatSubmitConstant.REPEAT_SUBMIT_KEY;

@Aspect
@Component
public class RepeatSubmitAspect {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(repeatSubmit)")
    public Object repeatSubmit(ProceedingJoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
        //获取注解参数
        String type = repeatSubmit.limitType().name();
        long lockTime = repeatSubmit.lockTime();

        //获取请求信息
        String requestURI = request.getRequestURI();
        String ipAddr = request.getRemoteAddr();
        String key = REPEAT_SUBMIT_KEY;

        //基于未登录的
        if(type.equalsIgnoreCase(RepeatSubmit.Type.PARAM.name())){
            MethodSignature methodSignature = (MethodSignature)point.getSignature();
            String className = methodSignature.getDeclaringTypeName();
            String methodName = methodSignature.getName();
            key+=String.format("%s-%s-%s-%s",ipAddr,requestURI,className,methodName);
        }else {
            //基于登录的令牌方式
            String token = request.getHeader("User-Agent");
            if(StringUtils.isEmpty(token)){
                key+=String.format("%s-%s",token,requestURI);
            }
        }
        boolean success = Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, "1", lockTime, TimeUnit.SECONDS));
        if(!success){
            throw new BizException("请勿重复提交订单");
        }
        try {
            //校验之后就需要执行后续逻辑
            return point.proceed();
        }finally {
            stringRedisTemplate.delete(key);
        }
    }
}
